using System;
using AntEater.ComponentModel.Validation;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Forms.Design;
using System.Drawing.Design;
using System.Globalization;

namespace AntEater.ComponentModel.BuildElements
{
    /// <summary>
    /// Provides the UsingTask build element.
    /// </summary>
    [Serializable]
    [BuildElement("UsingTask")]
    [Icon(typeof(UsingTaskBuildElement), "AntEater.ComponentModel.Resources.UsingTask.ico")]
    public class UsingTaskBuildElement : BuildElementBase
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="T:UsingTaskBuildElement"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        public UsingTaskBuildElement(BuildFileDefinition context)
            :base(context) {

            this._taskName = "undefined";
        }

        private string _assemblyFile;

        /// <summary>
        /// Gets or sets the assembly file.
        /// </summary>
        /// <value>The assembly file.</value>
        [BuildElementProperty("AssemblyFile", false, BuildElementPropertyType.String)]
        [Description("Either the AssemblyName or the AssemblyFile attribute is required.\nThe file path to the assembly. This attribute accepts both full and relative paths. Relative paths are relative to the current project directory. Using this attribute is equivalent to loading an assembly via the LoadFrom method in the .NET Framework.\nYou cannot use this attribute if the AssemblyName attribute is used.")]
        [Category("MsBuild")]
        [Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
        public string AssemblyFile {
            get { return _assemblyFile; }
            set {
                if (_assemblyFile != value) {
                    _assemblyFile = value;
                    OnPropertyChanged("AssemblyFile");
                }
            }
        }

        private string _assemblyName;

        /// <summary>
        /// Gets or sets the name of the assembly.
        /// </summary>
        /// <value>The name of the assembly.</value>
        [BuildElementProperty("AssemblyName", false, BuildElementPropertyType.String)]
        [Description("Either the AssemblyName or the AssemblyFile attribute is required.\nThe name of the assembly to load. The AssemblyName attribute accepts strong named assemblies although it is not required. Using this attribute is equivalent to loading an assembly via the Load method in the .NET Framework.\nYou cannot use this attribute if the AssemblyFile attribute is used.")]
        [Category("MsBuild")]
        public string AssemblyName {
            get { return _assemblyName; }
            set {
                if (_assemblyName != value) {
                    _assemblyName = value;
                    OnPropertyChanged("AssemblyName");
                }
            }
        }

        private string _condition;

        /// <summary>
        /// Gets or sets the condition.
        /// </summary>
        /// <value>The condition.</value>
        [BuildElementProperty("Condition", false, BuildElementPropertyType.Condition)]
        [Description("Optional attribute.\nCondition to be evaluated.")]
        [Category("MsBuild")]
        public string Condition {
            get { return _condition; }
            set {
                if (_condition != value) {
                    _condition = value;
                    OnPropertyChanged("Condition");
                }
            }
        }

        private string _taskName;

        /// <summary>
        /// Gets or sets the name of the task.
        /// </summary>
        /// <value>The name of the task.</value>
        [BuildElementProperty("TaskName", true, BuildElementPropertyType.String)]
        [Description("Required attribute.\nThe name of the task to reference from an assembly. If ambiguities are possible, this attribute should always specify full namespaces. If there are ambiguities, MSBuild will choose an arbitrary match, which could produce unexpected results.")]
        [Category("MsBuild")]
        public string TaskName {
            get { return _taskName; }
            set {
                if (_taskName != value) {
                    _taskName = value;
                    OnPropertyChanged("TaskName");
                }
            }
        }

        /// <summary>
        /// Determines whether this instance is valid.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 	<c>true</c> if this instance is valid; otherwise, <c>false</c>.
        /// </returns>
        public override bool IsValid {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Validates the specified recursive.
        /// </summary>
        /// <param name="recursive">if set to <c>true</c> [recursive].</param>
        /// <returns></returns>
        public override ReadOnlyCollection<ValidationResult> Validate(bool recursive) {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public override object Clone() {
            UsingTaskBuildElement newElement = base.Clone() as UsingTaskBuildElement;

            if (this._assemblyFile != null) {
                newElement._assemblyFile = this._assemblyFile.Clone() as string;
            }
            if (this._assemblyName != null) {
                newElement._assemblyName = this._assemblyName.Clone() as string;
            }
            if (this._condition != null) {
                newElement._condition = this._condition.Clone() as string;
            }
            if (this._taskName != null) {
                newElement._taskName = this._taskName.Clone() as string;
            }
            return newElement;
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </returns>
        public override string ToString() {
            return string.Format(CultureInfo.CurrentCulture, "{0} ({1})", base.ToString(), this.TaskName);
        }
    }
}
